package io.kiki.sba.registry.client.provider;

import io.kiki.sba.registry.client.api.ClientConfig;
import io.kiki.sba.registry.client.api.Publisher;
import io.kiki.sba.registry.client.api.registration.PublisherRegistration;
import io.kiki.sba.registry.client.task.TaskEvent;
import io.kiki.sba.registry.client.task.Worker;
import io.kiki.sba.registry.core.constants.EventTypeConstants;
import io.kiki.sba.registry.core.model.Data;
import io.kiki.sba.registry.core.model.PublisherRegister;
import lombok.Getter;
import lombok.Setter;

import java.util.*;

@Setter
@Getter
public class PublisherImpl extends AbstractInternalRegister implements Publisher {

    private final String REGIST_ID;
    private PublisherRegistration publisherRegistration;
    private Worker worker;
    private Collection<String> dataList;
    private ClientConfig clientConfig;


    PublisherImpl(PublisherRegistration publisherRegistration, Worker worker, ClientConfig clientConfig) {
        this.publisherRegistration = publisherRegistration;
        this.worker = worker;
        this.clientConfig = clientConfig;
        this.REGIST_ID = UUID.randomUUID().toString();
    }


    @Override
    public void republish(String... data) {
        if (isRefused()) {
            throw new IllegalStateException("Publisher is refused by server. Try to check your configuration.");
        }

        if (!isEnabled()) {
            throw new IllegalStateException("Unregistered publisher can not be reused.");
        }

        writeLock.lock();
        try {
            if (null != data) {
                this.dataList = Arrays.asList(data);
            }

            this.getPubVersion().incrementAndGet();
            this.setTimestamp(System.currentTimeMillis());
            this.waitToSync();
        } finally {
            writeLock.unlock();
        }
        this.worker.schedule(new TaskEvent(this));
    }


    @Override
    public void unregister() {
        if (isEnabled()) {
            super.unregister();
            this.worker.schedule(new TaskEvent(this));
        }
    }


    @Override
    public PublisherRegister assembly() {
        readLock.lock();
        PublisherRegister publisherRegister;
        try {
            publisherRegister = new PublisherRegister();
            publisherRegister.setRegistId(REGIST_ID);
            setAttributes(publisherRegistration, publisherRegister, clientConfig);
            // auth signature
            setAuthSignature(publisherRegister);

            if (isEnabled()) {
                publisherRegister.setEventType(EventTypeConstants.REGISTER);
                if (null != dataList) {
                    List<Data> dataBoxes = new ArrayList<Data>();
                    for (String data : dataList) {
                        dataBoxes.add(new Data(data));
                    }
                    publisherRegister.setDataList(dataBoxes);
                }
            } else {
                publisherRegister.setEventType(EventTypeConstants.UNREGISTER);
            }
        } finally {
            readLock.unlock();
        }
        return publisherRegister;
    }


    @Override
    public String getDataId() {
        return publisherRegistration.getDataId();
    }

    @Override
    public String getGroup() {
        return publisherRegistration.getGroup();
    }


    @Override
    public String getRegistId() {
        return REGIST_ID;
    }


}
